
/**
 * AppleIIGo
 * SmartPort Unit class
 * (C) 2008 by Marc S. Ressl (mressl@umich.edu)
 * Released under the GPL
 */

#ifndef SMARTPORTUNIT_H
#define SMARTPORTUNIT_H

#include <stdio.h>
#include "DiskDrive.h"
#include "FileDiskImage.h"

#define SMARTPORTPACKET_HEADERBYTENUM	8
#define SMARTPORTPACKET_FOOTERBYTENUM	3
#define SMARTPORTPACKET_DATAMAXBYTENUM	767

#define SMARTPORTPACKETTYPE_COMMAND		0x00
#define SMARTPORTPACKETTYPE_STATUS		0x01
#define SMARTPORTPACKETTYPE_DATA		0x02

#define SMARTPORTCOMMAND_STATUS			0x00
#define SMARTPORTCOMMAND_READBLOCK		0x01
#define SMARTPORTCOMMAND_WRITEBLOCK		0x02
#define SMARTPORTCOMMAND_FORMAT			0x03
#define SMARTPORTCOMMAND_CONTROL		0x04
#define SMARTPORTCOMMAND_INIT			0x05
#define SMARTPORTCOMMAND_OPEN			0x06
#define SMARTPORTCOMMAND_CLOSE			0x07
#define SMARTPORTCOMMAND_READ			0x08
#define SMARTPORTCOMMAND_WRITE			0x09

#define SMARTPORTERROR_NOERROR			0x00
#define SMARTPORTERROR_BADCMD			0x01
#define SMARTPORTERROR_BADPCNT			0x04
#define SMARTPORTERROR_BUSERR			0x06
#define SMARTPORTERROR_BADUNIT			0x11
#define SMARTPORTERROR_NOINT			0x1f
#define SMARTPORTERROR_BADCTL			0x21
#define SMARTPORTERROR_BADCTLPARM		0x22
#define SMARTPORTERROR_IOERROR			0x27
#define SMARTPORTERROR_NODRIVE			0x28
#define SMARTPORTERROR_NOWRITE			0x2b
#define SMARTPORTERROR_BADBLOCK			0x2d
#define SMARTPORTERROR_DISKSW			0x2e
#define SMARTPORTERROR_OFFLINE			0x2f
#define SMARTPORTERROR_DEVSPEC			0x30
#define SMARTPORTERROR_RESERVED			0x40
#define SMARTPORTERROR_NONFATAL			0x50

#define SMARTPORTSTATUS_OPEN			(1 << 0)
#define SMARTPORTSTATUS_INTERRUPTING	(1 << 1)
#define SMARTPORTSTATUS_WRITEPROTECTED	(1 << 2)
#define SMARTPORTSTATUS_FORMATENABLED	(1 << 3)
#define SMARTPORTSTATUS_ONLINE			(1 << 4)
#define SMARTPORTSTATUS_READENABLED		(1 << 5)
#define SMARTPORTSTATUS_WRITEENABLED	(1 << 6)
#define SMARTPORTSTATUS_BLOCKDEVICE		(1 << 7)

#define SMARTPORTACTION_NOREPLY			0
#define SMARTPORTACTION_REPLYACK		1
#define SMARTPORTACTION_REPLYPACKET		2

struct SmartPortPacket {
	UINT8 destinationId;
	UINT8 sourceId;
	UINT8 type;
	UINT8 auxType;
	UINT8 status;
	UINT32 dataByteNum;
	UINT8 data[SMARTPORTPACKET_DATAMAXBYTENUM];
};

class SmartPortUnit : public DiskDrive {
public:
	SmartPortUnit(UINT32 diskDriveType);
	~SmartPortUnit();
	
	bool mount(char * diskImagePath);
	void unmount();
	char * getDiskImagePath();
	
	UINT32 sendPacket(struct SmartPortPacket * packet);
	bool isReady();
	
protected:
	FileDiskImage * diskImage;
	
	char * deviceId;
	UINT8 deviceType;
	UINT8 deviceSubtype;
	UINT16 deviceVersion;
	
	void getStatus(struct SmartPortPacket * packet);
	UINT32 accessBlock(struct SmartPortPacket * packet, bool isWrite);
	void formatDevice(struct SmartPortPacket * packet);
	void sendControl(struct SmartPortPacket * packet);
	
	char * getDiskImageExtension(char * diskImagePath);
	UINT32 getDiskImageByteNum(char * diskImagePath);
};

#endif
